package com.easybuilder.core.im.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.easybuilder.common.enums.WSMessageType;
import com.easybuilder.core.im.dto.SysMessageDTO;
import com.easybuilder.core.im.dto.WSMessageDTO;
import com.easybuilder.core.im.entity.SysMessage;
import com.easybuilder.core.im.service.OfflinePushService;
import com.easybuilder.core.im.service.SysMessageService;
import com.easybuilder.core.rbac.entity.SysUser;
import com.easybuilder.core.rbac.service.SysUserService;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import tk.mybatis.mapper.entity.Example;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author ZXS
 * @version 1.0
 * @description 推送服务（推送离线消息）
 * @date 2022-3-24 22:49
 */
@Slf4j
@Component
public class OfflinePushServiceImpl implements OfflinePushService {

    @Autowired
    private SysMessageService messageService;
    @Autowired
    private SysUserService userService;

    /** 推送离线消息
     * @param userId 登陆用户id
     * @param channel 用户连接通道
     * */
    @Override
    public void push(Long userId, Channel channel) {
        // 查询当前用户下的所有离线消息
        Example example = new Example(SysMessage.class);
        example.createCriteria().andEqualTo("receiverId", userId).andEqualTo("messageStatus", 0).andEqualTo("dropStatus", 0);
        List<SysMessage> sysMessages = messageService.selectByExample(example);
        if (sysMessages != null && sysMessages.size() > 0) {
            SysUser user = userService.getUserById(userId);
            // ws消息体
            WSMessageDTO result = new WSMessageDTO();
            // 构建离线消息列表（离线消息按照发送人分组，并设置发送人信息）
            List<WSMessageDTO.OfflineMessageSender> offlineMessageList = buildOfflineMessageList(sysMessages);
            // 推送离线消息
            result.setOfflineMessageSenders(offlineMessageList);
            result.setType(WSMessageType.OFFLINE_MESSAGE_PUSH.value());
            channel.writeAndFlush(new TextWebSocketFrame(JSONObject.toJSONString(result)));
            log.info("向用户{}推送离线消息完成", user);
        }


    }

    /** 构建离线消息列表 */
    private List<WSMessageDTO.OfflineMessageSender> buildOfflineMessageList(List<SysMessage> sysMessages) {
        List<SysMessageDTO> offlineMessageList = new ArrayList<>();
        for (SysMessage sysMessage : sysMessages) {
            SysMessageDTO messageDTO = new SysMessageDTO();
            BeanUtils.copyProperties(sysMessage, messageDTO);
            offlineMessageList.add(messageDTO);
        }
        // 设置消息发送人的信息（昵称、头像）
        setSenderInfo(offlineMessageList);
        // 将离线消息列表，按照消息发送人进行分组，并按照时间正序排序
        Map<Long, List<SysMessageDTO>> map = offlineMessageList.stream().collect(Collectors.groupingBy(SysMessageDTO::getSenderId));
        // 构建最终结果
        List<WSMessageDTO.OfflineMessageSender> offlineMessageSenders = new ArrayList<>();
        Set<Long> keys = map.keySet();
        for (Long key : keys) {
            List<SysMessageDTO> messages = map.get(key);
            if (messages != null && messages.size() > 0) {
                SysMessageDTO message = messages.get(0);
                WSMessageDTO.OfflineMessageSender offlineMessageSender = new WSMessageDTO.OfflineMessageSender();
                offlineMessageSender.setSenderId(message.getSenderId());
                offlineMessageSender.setSenderNickname(message.getSenderNickname());
                offlineMessageSender.setSenderImg(message.getSenderImg());
                offlineMessageSender.setMessageList(messages);
                offlineMessageSenders.add(offlineMessageSender);
            }
        }
        return offlineMessageSenders;
    }

    private void setSenderInfo(List<SysMessageDTO> offlineMessageList) {
        // 获取离线消息的所有发送人id，并去重
        List<Long> senderIds = offlineMessageList.stream().map(item->{return item.getSenderId();}).distinct().collect(Collectors.toList());
        // 获取发送人集合
        List<SysUser> senders = userService.selectByUserIds(senderIds);
        // 给消息设置发送人信息
        for (SysMessageDTO sysMessageDTO : offlineMessageList) {
            for (SysUser sender : senders) {
                if (sender.getId().equals(sysMessageDTO.getSenderId())) {
                    sysMessageDTO.setSenderNickname(sender.getNickname());
                    sysMessageDTO.setSenderImg(sender.getImg());
                    break;
                }
            }
        }

    }
}
